#ifndef GLWIDGET_H
#define GLWIDGET_H

#include <QGLWidget>
#include <QGLShaderProgram>
#include <QCursor>
#include <QTimer>
#include <QMap> // Para tener controles fluidos
#include <fstream>
#include <iostream>
#include "controls.h"
#include "particlesystem.h"
#include "vobject.h"
#include "particlesystem.h"
using namespace std;

class GLWidget : public QGLWidget
{
    Q_OBJECT
public:
    explicit GLWidget(QWidget *parent = 0);

    void paintGL();
    void initializeGL();
    void resizeGL(int w, int h);
    void UpsideDownMC();
    void MoveMC(int dir);

    // Funciones y demas para la escena
    void SetScene(QString url);
    QVector3D AmbientColor;
    float AmbientIntensity;
    QString AssetsPath;

    // Controller Functions
    Controls *Controller;
    void keyPressEvent(QKeyEvent *e);
    void keyReleaseEvent(QKeyEvent *e);
    void timerEvent(QTimerEvent *e);
    void mouseMoveEvent(QMouseEvent *e);
    void SwitchAnaglyph();
    void SwitchCyanAnaglyph();
    void LoadRAW(QString URL,
                 VObject::NORMALMODE normcalc,
                 int xsize, int ysize, int zsize,
                 int bitdepth,
                 int isovalue,
                 int maxpoligon,
                 int xmax, int ymax, int zmax);

    // Estas funciones le otorgaran el control sobre un objeto/lampara/sistema de particulas a quien la solicite
    VObject* getObjectByName(QString input);
    ParticleSystem* getPartSystemByName(QString input);
    bool ChangeParticleTexture(QString pname, QString url);

private:
    QMap <int, bool> Keys; // Para los controles fluidos
    QCursor* Crosshair;
    QPoint LastPoint;
    bool TRACKMOUSE;
    bool GOANAGLYPH;
    bool CYANANAGLYPH;
    bool RENDERWIREFRAME;
    bool OVERLAYWIREFRAME;

    // Shaders
    QGLShader *fShader, *vShader;
    QGLShaderProgram *MeshesProgram;
    QGLShaderProgram *LightsProgram;


    // Objetos, sistemas y luces en escena
    QVector <VObject *> *Objects;
    QVector <VObject *> *Lights;
    QVector <ParticleSystem *> *ParticleSystems;

    // Utilidades y demas
    float* ReadVec3(FILE* input);
    float* ReadVec4(FILE* input);
    float ReadFloat(FILE* input);
    int ReadInt(FILE* input);

signals:
    void keypressed (int keypressed, QPoint pos);
    void LightTweak (int keypressed);
    void mousemoved (QPoint pos);
    void LeftPanelSwitched (); // Para esconder/mostrar las propiedades del objeto
    void RightPanelSwitched (); // Para esconder/mostrar las opciones de la escena
    void AnaglyphChanged(bool value);
    void CyanAnaglyphChanged(bool value);
    void WrongThreshold();
    void ReconstructionInfo (int size, QString dimensions, int bitdepth, int poligoncount,
                                 int vertexcount, int isovalue, int elapsed);

    void ObjectAdded(QString output);
    void LightAdded(QString output);
    void ParticleSystemAdded(QString output);

public slots:
    void SwitchAnaglyph(bool value);
    void SwitchCyanAnaglyph(bool value);
    void SetZeroParallax(double value);
    void SetEyeDistance(double value);
    void SwitchWireFrame(bool value);
    void SwitchOverlayWireFrame(bool value);

};

#endif // GLWIDGET_H
